package net.aiion.weave;

import java.lang.reflect.Method;

import net.aiion.weave.spi.injection.annotations.Inject;
import net.aiion.weave.spi.interception.InterceptionContext;
import net.aiion.weave.spi.interception.Interceptor;
import net.aiion.weave.spi.interception.annotations.Intercepts;

public class InterceptingClass implements Interceptor
{
    public InterceptingClass() {
    }

    @Intercepts(Inject.class)
    public Object interceptCall1(InterceptionContext aInterceptionContext) {
        return null;
    }

    // Produces error!
    // @Intercepts(Inject.class)
    // public Object createObject2(InterceptionContext aInterceptionContext) {
    // return null;
    // }

    @Intercepts(Deprecated.class)
    public Object createObject3(InterceptionContext aInterceptionContext) {
        return null;
    }

    @Override
    public Object interceptInvocation(InterceptionContext aInterceptionContext) {
        // mv = cw.visitMethod(ACC_PUBLIC, "interceptInvocation",
        // "(Lnet/aiion/weave/interception/spi/InterceptionContext;)Ljava/lang/Object;", null, null);
        // mv.visitCode();
        //
        // mv.visitVarInsn(ALOAD, 1);
        // mv.visitMethodInsn(INVOKEINTERFACE, "net/aiion/weave/interception/spi/InterceptionContext",
        // "getInterceptedMethod", "()Ljava/lang/reflect/Method;");
        // mv.visitVarInsn(ASTORE, 2);
        //
        // Label l2 = new Label();
        // mv.visitVarInsn(ALOAD, 2);
        // mv.visitLdcInsn(Type.getType("Lnet/aiion/weave/injection/Inject;"));
        // mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/reflect/Method", "isAnnotationPresent", "(Ljava/lang/Class;)Z");
        // mv.visitJumpInsn(IFEQ, l2);
        // mv.visitVarInsn(ALOAD, 0);
        // mv.visitVarInsn(ALOAD, 1);
        // mv.visitMethodInsn(INVOKEVIRTUAL, "net/aiion/weave/InterceptingClass", "interceptCall1",
        // "(Lnet/aiion/weave/interception/spi/InterceptionContext;)Ljava/lang/Object;");
        // mv.visitInsn(ARETURN);
        // mv.visitLabel(l2);
        //
        // Label l4 = new Label();
        // mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] {
        // "java/lang/reflect/Method"
        // }, 0, null);
        // mv.visitVarInsn(ALOAD, 2);
        // mv.visitLdcInsn(Type.getType("Ljava/lang/Deprecated;"));
        // mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/reflect/Method", "isAnnotationPresent", "(Ljava/lang/Class;)Z");
        // mv.visitJumpInsn(IFEQ, l4);
        // mv.visitVarInsn(ALOAD, 0);
        // mv.visitVarInsn(ALOAD, 1);
        // mv.visitMethodInsn(INVOKEVIRTUAL, "net/aiion/weave/InterceptingClass", "interceptCall1",
        // "(Lnet/aiion/weave/interception/spi/InterceptionContext;)Ljava/lang/Object;");
        // mv.visitInsn(ARETURN);
        // mv.visitLabel(l4);
        //
        // mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
        // mv.visitVarInsn(ALOAD, 1);
        // mv.visitMethodInsn(INVOKEINTERFACE, "net/aiion/weave/interception/spi/InterceptionContext",
        // "forwardInterception", "()Ljava/lang/Object;");
        // mv.visitInsn(ARETURN);
        // mv.visitMaxs(2, 3);
        // mv.visitEnd();

        Method interceptedMethod = aInterceptionContext.getInterceptedMethod();
        if (interceptedMethod.isAnnotationPresent(Inject.class)) {
            return interceptCall1(aInterceptionContext);
        }

        if (interceptedMethod.isAnnotationPresent(Deprecated.class)) {
            return interceptCall1(aInterceptionContext);
        }

        return aInterceptionContext.forwardInterception();
    }
}
